ko.bindingHandlers.spinner = {
	init : function(element, valueAccessor, allBindingsAccessor) {
		//initialize datepicker with some optional options
		var options = allBindingsAccessor().spinnerOptions || {};
		$(element).spinner(options);

		

		//handle the field changing
		ko.utils.registerEventHandler(element, "spinchange", function() {
			var observable = valueAccessor();
			observable($(element).spinner("value"));
		});

		//handle disposal (if KO removes by the template binding)
		ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
			$(element).spinner("destroy");
		});

	},
	update : function(element, valueAccessor) {
		var value = ko.utils.unwrapObservable(valueAccessor()), current = $(element).spinner("value");

		if (value !== current) {
			$(element).spinner("value", value);
		}
	}
};
ko.bindingHandlers.custSpinner = {

	init : function(element, valueAccessor, allBindingsAccessor, viewModel) {
		//init logic
		//console.log("custombinding init");
		$(element).timespinner();
	},
	update : function(element, valueAccessor, allBindingsAccessor, viewModel) {
		//update logic
		//console.log("custombinding update");
		$(element).timespinner("destroy");
		$(element).timespinner();
	}
};

ko.bindingHandlers.scheduleDialog = {

	init : function(element, valueAccessor, allBindingsAccessor, viewModel) {
		//init logic
		//console.log("dialog init");
	},
	update : function(element, valueAccessor, allBindingsAccessor, viewModel) {
		//update logic
		//console.log("dialog update");
		//	$(element).dialog( "destroy" );
		var options = valueAccessor() || {};
		$(element).dialog({
			autoOpen : false,
			width : 650,
			modal : true
		});
		
		$(element).dialog("option", "position", "center");
	}
};

ko.bindingHandlers.deleteDialog = {

	init : function(element, valueAccessor, allBindingsAccessor, viewModel) {
		//init logic
		//console.log("dialog init");
	},
	update : function(element, valueAccessor, allBindingsAccessor, viewModel) {
		//update logic
		//console.log("dialog update");
		//	$(element).dialog( "destroy" );
		var options = valueAccessor() || {};
		$(element).dialog({
			autoOpen : false,
			width : 420,
			modal : true
		});
		
		$(element).dialog("option", "position", "center");
	}
};

/*
ko.bindingHandlers.jqueryUIBindingstimer = {

init : function(element, valueAccessor) {

jQuery(element).timepicker({
hourGrid : 4,
minuteGrid : 10,
timeFormat : 'HH:mm',
onClose : function(dateText, inst) {
console.log(" ============================================ onClose");
scheduleVM.validateUnutilizedDuration();
},
onSelect : function(selectedDateTime) {
//endDateTextBox.datetimepicker('option', 'minDate', startDateTextBox.datetimepicker('getDate') );
}
});

},

update : function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {

}
};
*/

//format date
ko.bindingHandlers.dateString = {
	update : function(element, valueAccessor, allBindingsAccessor, viewModel) {
		var value = valueAccessor(), allBindings = allBindingsAccessor();
		var valueUnwrapped = ko.utils.unwrapObservable(value);
		var pattern = allBindings.datePattern || 'MM/dd/yyyy';
		//var pattern = allBindings.datePattern || 'dd/mm/yy';
		$(element).text(valueUnwrapped.toString(pattern));
	}
};

ko.bindingHandlers.datepicker = {
	init : function(element, valueAccessor, allBindingsAccessor) {
		//console.log("element >>>>>>>>>>> : ", element)
		$(element).datepicker({
			changeMonth : true,
			changeYear : true,
			minDate : aypStartDate,
			maxDate : aypEndDate,
			beforeShowDay : highlightDays,
			dateFormat : "dd-mm-yy"
		});
		//initialize datepicker with some optional options
		var options = allBindingsAccessor().datepickerOptions || {};
		//$(element).datepicker(options);

		//handle the field changing
		ko.utils.registerEventHandler(element, "change", function() {
			var observable = valueAccessor();
			var myVal = $(element).datepicker("getDate");
			var date = Date.parse($(element).val());
			//observable($(element).datepicker("getDate"));
			observable($(element).datepicker("getDate").toString("yyyy-MM-dd"));
			//observable(date.toString("yyyy-MM-dd"));
			console.log("date.toString(MM-dd-yyyy) : ", date.toString("MM-dd-yyyy"));

			tab3AssessmentViewModel.onDateChange(element);
		});

		ko.utils.registerEventHandler(element, 'focusin', function() {

			//tab3AssessmentViewModel.onFocusIn(element)
		});

		//handle disposal (if KO removes by the template binding)
		ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
			$(element).datepicker("destroy");
		});

	},
	update : function(element, valueAccessor) {

		var value = ko.utils.unwrapObservable(valueAccessor());

		//handle date data coming via json from Microsoft
		if (String(value).indexOf('/Date(') == 0) {
			//value = new Date(parseInt(value.replace(/\/Date\((.*?)\)\//gi, "$1")));
		}

		var d = Date.parse(value);
		var current = $(element).datepicker("getDate");
		var d = Date.parse(value);
		if (value - current !== 0) {
			//$(element).datepicker("setDate", value);

			//$(element).datepicker("setDate", d.toString("yyyy-MM-dd"));
			/**
			 * changed from top to bottom on 2nd Aug 2013
			 */
			$(element).datepicker("setDate", d.format("dd-mm-yyyy"));
		}

	}
};

ko.bindingHandlers.dialog = {
	init : function(element, valueAccessor, allBindingsAccessor) {
		var options = ko.utils.unwrapObservable(valueAccessor()) || {};
		//do in a setTimeout, so the applyBindings doesn't bind twice from element being copied and moved to bottom
		setTimeout(function() {
			options.close = function() {
				allBindingsAccessor().dialogVisible(false);
			};

			$(element).dialog(ko.toJS(options));
		}, 0);

		//handle disposal (not strictly necessary in this scenario)
		ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
			$(element).dialog("destroy");
		});
	},
	update : function(element, valueAccessor, allBindingsAccessor) {
		var shouldBeOpen = ko.utils.unwrapObservable(allBindingsAccessor().dialogVisible), $el = $(element), dialog = $el.data("uiDialog") || $el.data("dialog"), options = valueAccessor();
		
		//don't call dialog methods before initilization
		if (dialog) {
			$el.dialog( shouldBeOpen ? "open" : "close");
			$el.dialog("option", "position", "center");
			for (var key in options) {
				if (ko.isObservable(options[key])) {
					$el.dialog("option", key, options[key]());
					
				}
			}
		}
	}
};

ko.bindingHandlers.accordion = {
	init : function(element, valueAccessor) {
		var options = valueAccessor() || {};
		setTimeout(function() {
			$(element).accordion(options);
		}, 0);

		//handle disposal (if KO removes by the template binding)
		ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
			$(element).accordion("destroy");
		});
	},
	update : function(element, valueAccessor) {
		var options = valueAccessor() || {};
		//$(element).accordion("destroy").accordion(options);

		if ( typeof $(element).data("ui-accordion") != "undefined") {
			$(element).accordion("destroy").accordion(options);
		}
	}
}

ko.bindingHandlers.NumChecked = {
	update : function(element, valueAccesor) {
		var func = valueAccesor();
		if ( typeof (func) == 'function' && func() == true)
			func(1);
		else if (( typeof (func) == 'function'))
			func(0);
	}
};
ko.bindingHandlers.uniqueId = {
	init : function(element, valueAccessor) {
		var value = valueAccessor();
		value.id = value.id || ko.bindingHandlers.uniqueId.prefix + (++ko.bindingHandlers.uniqueId.counter);

		element.id = value.id;
	},
	counter : 0,
	prefix : "unique"
};

ko.bindingHandlers.uniqueFor = {
	init : function(element, valueAccessor) {
		var value = valueAccessor();
		value.id = value.id || ko.bindingHandlers.uniqueId.prefix + (++ko.bindingHandlers.uniqueId.counter);

		element.setAttribute("for", value.id);
	}
};

ko.bindingHandlers.autoComplete = {
	findSelectedItem : function(dataSource, binding, selectedValue) {
		var unwrap = ko.utils.unwrapObservable;
		//Go through the source and find the id, and use its label to set the autocomplete
		var source = unwrap(dataSource);
		var valueProp = unwrap(binding.optionsValue);

		var selectedItem = ko.utils.arrayFirst(source, function(item) {
			if (unwrap(item[valueProp]) === selectedValue)
				return true;
		}, this);

		return selectedItem;
	},
	buildDataSource : function(dataSource, labelProp, valueProp) {
		var unwrap = ko.utils.unwrapObservable;
		var source = unwrap(dataSource);
		var mapped = ko.utils.arrayMap(source, function(item) {
			var result = {};
			result.label = labelProp ? unwrap(item[labelProp]) : unwrap(item).toString();
			//show in pop-up choices
			result.value = valueProp ? unwrap(item[valueProp]) : unwrap(item).toString();
			//value
			return result;
		});
		return mapped;
	},
	init : function(element, valueAccessor, allBindingsAccessor, viewModel) {
		var unwrap = ko.utils.unwrapObservable;
		var dataSource = valueAccessor();
		var binding = allBindingsAccessor();
		var valueProp = unwrap(binding.optionsValue);
		var labelProp = unwrap(binding.optionsText) || valueProp;
		var displayId = $(element).attr('id') + '-display';
		var displayElement;
		var options = {};

		if (binding.autoCompleteOptions) {
			options = $.extend(options, binding.autoCompleteOptions);
		}

		//Create a new input to be the autocomplete so that the label shows
		// also hide the original control since it will be used for the value binding
		$(element).hide();
		$(element).after('<input type="text" id="' + displayId + '" />')
		displayElement = $('#' + displayId);

		//handle value changing
		var modelValue = binding.value;
		if (modelValue) {
			var handleValueChange = function(event, ui) {
				var labelToWrite = ui.item ? ui.item.label : null
				var valueToWrite = ui.item ? ui.item.value : null;
				//The Label and Value should not be null, if it is
				// then they did not make a selection so do not update the
				// ko model
				if (labelToWrite && valueToWrite) {
					if (ko.isWriteableObservable(modelValue)) {
						//Since this is an observable, the update part will fire and select the
						//  appropriate display values in the controls
						modelValue(valueToWrite);
					} else {//write to non-observable
						if (binding['_ko_property_writers'] && binding['_ko_property_writers']['value']) {
							binding['_ko_property_writers']['value'](valueToWrite);
							//Because this is not an observable, we have to manually change the controls values
							// since update will not do it for us (it will not fire since it is not observable)
							displayElement.val(labelToWrite);
							$(element).val(valueToWrite);
						}
					}
				}
				//They did not make a valid selection so change the autoComplete box back to the previous selection
				else {
					var currentModelValue = unwrap(modelValue);
					//If the currentModelValue exists and is not nothing, then find out the display
					// otherwise just blank it out since it is an invalid value
					if (!currentModelValue)
						displayElement.val('');
					else {
						//Go through the source and find the id, and use its label to set the autocomplete
						var selectedItem = ko.bindingHandlers.autoComplete.findSelectedItem(dataSource, binding, currentModelValue);

						//If we found the item then update the display
						if (selectedItem) {
							var displayText = labelProp ? unwrap(selectedItem[labelProp]) : unwrap(selectedItem).toString();
							displayElement.val(displayText);
						}
						//if we did not find the item, then just blank it out, because it is an invalid value
						else {
							displayElement.val('');
						}
					}
				}

				return false;
			};

			var handleFocus = function(event, ui) {
				$(displayElement).val(ui.item.label);
				return false;
			};

			options.change = handleValueChange;
			options.select = handleValueChange;
			options.focus = handleFocus;
			//options.close = handleValueChange;
		}

		//handle the choices being updated in a Dependant Observable (DO), so the update function doesn't
		// have to do it each time the value is updated. Since we are passing the dataSource in DO, if it is
		// an observable, when you change the dataSource, the dependentObservable will be re-evaluated
		// and its subscribe event will fire allowing us to update the autocomplete datasource
		var mappedSource = ko.dependentObservable(function() {
			return ko.bindingHandlers.autoComplete.buildDataSource(dataSource, labelProp, valueProp);
		}, viewModel);
		//Subscribe to the knockout observable array to get new/remove items
		mappedSource.subscribe(function(newValue) {
			displayElement.autocomplete("option", "source", newValue);
		});

		options.source = mappedSource();

		displayElement.autocomplete(options);
	},
	update : function(element, valueAccessor, allBindingsAccessor, viewModel) {
		//update value based on a model change
		var unwrap = ko.utils.unwrapObservable;
		var dataSource = valueAccessor();
		var binding = allBindingsAccessor();
		var valueProp = unwrap(binding.optionsValue);
		var labelProp = unwrap(binding.optionsText) || valueProp;
		var displayId = $(element).attr('id') + '-display';
		var displayElement = $('#' + displayId);
		var modelValue = binding.value;

		if (modelValue) {
			var currentModelValue = unwrap(modelValue);
			//Set the hidden box to be the same as the viewModels Bound property
			$(element).val(currentModelValue);
			//Go through the source and find the id, and use its label to set the autocomplete
			var selectedItem = ko.bindingHandlers.autoComplete.findSelectedItem(dataSource, binding, currentModelValue);
			if (selectedItem) {
				var displayText = labelProp ? unwrap(selectedItem[labelProp]) : unwrap(selectedItem).toString();
				displayElement.val(displayText);
			}
		}
	}
};

